<?php

class NewCultivateService extends AbstractService
{

    /**
     * @var NewCultivateService
     */
    private static $instance;

    /**
     * Get the instance of NewCultivateService
     * @return NewCultivateService
     */
    public static function get() {
        if (!self::$instance) {
            self::$instance = new NewCultivateService();
        }
        return self::$instance;
    }

    /**
     * Construction.
     */
    protected function __construct() {
        parent::__construct();
    }

    /**
     * 处理用户创建时的逻辑
     * @param int $shardId
     * @return void
     */
    public function handleCreate($shardId) {

    }

    /**
     * 处理用户登录时的逻辑
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId) {
        // do nothing
    }

    /**
     * 处理 service 对外提供的全量数据
     * @param int $userId
     * @return array
     */
    public function info($userId) {
        return SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
    }

    public function getInfo($userId,$reqTime) {
        $data = $this->refreshCultivateHarvestTime($userId,$reqTime);
        if (!$data) {
            $data['count'] = 0;
        }
        $data['code'] = 1;
        return $data;
    }

    /**
     * 培育/变色
     * @param $landId
     * @param $userId
     * @param $flowerId
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function plant($userId,$landId,$flowerId,$reqTime) {
        /**
         * @var NewCultivateLandVoList $userLandList
         * @var NewCultivateLandVo $userLand
         * @var ModuleItemVoList $itemList
         */
        $flowerInfo = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SEED_CONDITION, $flowerId, true);
        $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        if ($profile->getLevel() < $flowerInfo['unlockLv']) {
            throw new SzException(29002); // 用户等级不够
        }

        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId);
        if ($userLand->getFlowerId()) {
            throw new SzException(29007, $landId); // 已种植/变色
        }
        if ($flowerInfo['unlockType'] == 4) {
            $itemList = SzPersister::get()->getVoList($userId, ModuleItemConst::ORM_NAME_ITEM);
            $item = $itemList->getElementsByItemDefId($flowerInfo['taskId']);
            if (is_null($item)) {
                throw new SzException(29002);
            }
        }

        $seedList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_PLANT_SEED);
        $seedVo = $seedList->getElement($flowerId, false);
        if ($seedVo) {
            throw new SzException(29008, $flowerId); // 已解锁
        }

        $this->clearCultivateHarvestTime($userId,$reqTime);

        // 扣除道具
        $inputTid = '';
        foreach ($flowerInfo['itemId'][0] as $entityId => $count) {
            GameService::get()->handleEntity($userId, $entityId, $count, true);
            $inputTid .= $entityId . ':' . abs($count) . '|';
        }
        CommonFunctionService::get()->reportResourceUseDetails(99999996,$userId,0,$inputTid,'plant');//消耗资源上报

        // 成功率
        $rand = mt_rand(1,100);
        if ($rand <= $flowerInfo['successRate']) {
            $harvestTime = $reqTime + $flowerInfo['waitingTime'];
            $userLand->setFlowerId($flowerId);
            $userLand->setHarvestTime($harvestTime);
            $userLand->setUnlock_res(1);
            $userLandList->updateElement($landId, $userLand);
            SzPersister::get()->setVoList($userLandList);
            $unlockRes = 1;
            $str = '&success';
        } else {
            $unlockRes = 0;
            $str = '&fail';
        }

        // 数据采集:鲜花培育/变色
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:flower|action:cultivate|',
                'item' => $flowerId,
                'value' => 1
            )
        ));

        // 数据采集:鲜花培育/变色消耗
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
            'clientData' => array(
                'tid' => $inputTid,
                'item' => 'flower_cultivate&' . $flowerId
            )
        ));

        // 数据采集:鲜花培育/变色结果
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:cultivate|action:result|',
                'item' => $flowerId.$str,
                'value' => 1
            )
        ));

        return array('landList'=>$userLand->toArray(),'unlockRes'=>$unlockRes,'flowerId'=>$flowerId);
    }

    /**
     * 加速
     * @param $landId
     * @param $userId
     * @param $reqTime
     * @return array|void
     * @throws SzException
     */
    public function seedUp($userId,$landId,$reqTime) {
        /**
         * @var NewCultivateLandVoList $userLandList
         * @var NewCultivateLandVo $userLand
         */
        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId);

        $harvestTime = $userLand->getHarvestTime();

        if ($harvestTime <= $reqTime) {
            return $userLand->toArray();
        }
        $flowerId = $userLand->getFlowerId();

        $config = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'CultivatingTime', true);

        if (!$config) {
            return $userLand->toArray();
        }
        list($min,$val) = explode(',',$config['value']);

        $count = ceil(($harvestTime - $reqTime) / 60 / $min) * $val;
        $entityId = GameConst::ENTITY_ACTION_CONSUME_MONEY;
        if ($flowerId != 40011009) {
            GameService::get()->handleEntity($userId, $entityId, $count, true);
        } else {
            $count = 0;
        }
        CommonFunctionService::get()->reportResourceUseDetails(99999982,$userId,0,$entityId.':'.$count.'|','seedUp');//消耗资源上报

        $userLand->setHarvestTime($reqTime);
        $userLandList->updateElement($landId, $userLand);
        SzPersister::get()->setVoList($userLandList);
        $flowerId = $userLand->getFlowerId();
        // 数据采集:清除CD
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:cultivate|action:clearCD|',
                'item' => $flowerId,
                'value' => 1
            )
        ));
        // 数据采集:消耗钻石
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USE_GOLD, array(
            'clientData' => array(
                'item' => 'cultivate&clearCD',
                'value' => $count
            )
        ));
        return array('landList'=>$userLand->toArray(),'cost'=>$count);
    }

    /**
     * 补全道具
     * @param $userId
     * @param $flowerId
     * @return int
     * @throws SzException
     */
    public function repair($userId,$flowerId,$itemId) {
        $flowerInfo = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SEED_CONDITION, $flowerId, true);
        $profile = SzPersister::get()->getVo($userId, ModuleProfileConst::ORM_NAME_PROFILE);
        if ($profile->getLevel() < $flowerInfo['unlockLv']) {
            throw new SzException(29002); // 用户等级不够
        }

        $flowerPre = substr($flowerId,0,4);
        if ($flowerPre == 4001){
            $seedList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_PLANT_SEED);
            $seedVo = $seedList->getElement($flowerId, false);
        } else{
            $seedList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_SUCCULENT_SEED);
            $seedVo = $seedList->getElement($flowerId, false);
         }


        if ($seedVo) {
            throw new SzException(29008, $flowerId); // 已解锁
        }

        /**
         * @var ModuleItemVoList $itemList
         */
        $itemList = SzPersister::get()->getVoList($userId, ModuleItemConst::ORM_NAME_ITEM);
        $haveCount = $itemList->getItemDefCount($itemId);
        $differCount = 0;
        foreach ($flowerInfo['itemId'][0] as $entityId => $count) {
            list(,, $subId) = EntityService::get()->parseEntityId($entityId);
            if ($subId == $itemId) {
                if ($haveCount >= $count) {
                    return array($itemId=>0);
                }
                $differCount = $count - $haveCount;
                break;
            }
        }
        $itemSetting = SzConfig::get()->loadAppConfig(ModuleItemConst::CONFIG_ITEM_DEFS, $itemId, true);
        if ($itemSetting['quickBuyCost'] <= 0) {
            throw new SzException(30106, $itemId, ModuleItemConst::MODULE_NAME);
        }
        // 扣除钻石
        $entityId = GameConst::ENTITY_ACTION_CONSUME_MONEY;
        GameService::get()->handleEntity($userId, $entityId, ($differCount * $itemSetting['quickBuyCost']), true);
        CommonFunctionService::get()->reportResourceUseDetails(99999978,$userId,0,$entityId.':'.($differCount * $itemSetting['quickBuyCost']).'|','repair');//消耗资源上报

        // 增加道具
        list($itemList) = ItemService::get()->processItems($userId, [$itemId => $differCount], $itemList);
        SzPersister::get()->setVoList($itemList);

        // 数据采集:补全的道具
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:cultivate|action:supplement|',
                'item' => $flowerId.'&'.$itemId.'&'.$differCount,
                'value' => 1
            )
        ));

        // 数据采集:消耗钻石
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USE_GOLD, array(
            'clientData' => array(
                'item' => 'cultivate&supplement',
                'value' => ($differCount * $itemSetting['quickBuyCost'])
            )
        ));

        return array($itemId=>$differCount);
    }

    /**
     * 收获
     * @param $userId
     * @param $landId
     * @param $reqTime
     * @return array
     * @throws SzException
     */
    public function harvest($userId,$landId,$reqTime) {
        $this->refreshCultivateHarvestTime($userId,$reqTime);
        /**
         * @var NewCultivateLandVoList $userLandList
         * @var NewCultivateLandVo $userLand
         */
        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId);

        $harvestTime = $userLand->getHarvestTime();
        $flowerId = $userLand->getFlowerId();

        if ($harvestTime > $reqTime) {
            throw new SzException(20255, array($flowerId, $reqTime, $harvestTime));
        }

        // 解锁
        $seedList = SeedService::get()->unlockSeed($userId, $flowerId);
        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        $redisDb->hSet(GameConst::CACHE_KEY_NEW_CULTIVATE_WATCH.$userId,$flowerId,$reqTime);
        NewTaskService::get()->setProgress($userId,GameConst::TASK_CULTIVATE,count($seedList->toArray()));
        TreeService::get()->setProgress($userId,GameConst::TREE_TASK_CULTIVATE_FLOWER,count($seedList->toArray()));

        $userLand->setUnlock_res(0);
        $userLand->setHarvestTime(0);
        $userLand->setFlowerId(0);
        $userLand->setVideoTime(0);
        $userLandList->updateElement($landId, $userLand);
        SzPersister::get()->setVoList($userLandList);

        $cropSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_PLANT_CROP, $flowerId, true);
        $amount = 1;
        list($itemList) = ItemService::get()->processItems($userId, [$cropSetting['exp'] => $amount]);
        SzPersister::get()->setVoList($itemList);
        $outTid = $cropSetting['exp'].':'.$amount.'|';

        // 数据采集
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_OUTPUT, array(
            'clientData' => array(
                'tid' => $outTid,
                'item' => 'cultivate&'.$flowerId,
            )
        ));

        // 数据采集
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:cultivate|action:receive|',
                'item' => $flowerId,
                'value' => 1
            )
        ));

        // 数据采集
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_UPGRADE, array(
            'clientData' => array(
                'tid' => 'objective:cultivate_unlock|item:'.$flowerId.'|',
                'item' => 'fromlevel:|changelev:unlock|targetlev:|',
                'value' => 1
            )
        ));

        // 种子等级排行榜
        $isUp = SeedService::get()->setFlowerLevel($userId,GameService::get()->getReqTime(),true);

        //社团竞赛任务进度添加
        UnionCompetitionService::get()->addCompetitionTaskProcess($userId,GameConst::UNION_COMPETITION_TASK_4, $reqTime,1);

        return $seedList->toArray();
    }

    /**
     * 观看
     * @param $userId
     * @param $flowerIds
     * @return int
     */
    public function watch($userId,$flowerIds) {
        $redisDb = SzDbFactory::get()->getDb(null, SzAbstractDb::DB_TYPE_REDIS);
        foreach ($flowerIds as $flowerId) {
            $redisDb->hDel(GameConst::CACHE_KEY_NEW_CULTIVATE_WATCH.$userId,$flowerId);
        }
        return 1;
    }

    /** 免费地块解锁
     * @param $userId
     * @throws SzException
     */
    public function initLand($userId) {
        $landId = 21030001; // 暂时固定值  后期修改
        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId, false);
        if (!$userLand) {
            $cultivateLand = new NewCultivateLandVo($userId, $landId, 0, 0, 0, 0,true);
            $userLandList->addElement($cultivateLand);
            $userLandList->setElement($landId, $cultivateLand);
        }
        SzPersister::get()->setVoList($userLandList);
        return;
    }

    /**
     * @param $userId
     * @throws SzException
     */
    public function refreshCultivateHarvestTime($userId,$reqTime) {
        /**
         * @var $shareList ShareVoList
         * @var $share ShareVo
         * @var NewCultivateLandVoList $userLandList
         * @var NewCultivateLandVo $userLand
         */
        $shareList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_SHARE);
        $share = $shareList->getElement(GameConst::CULTIVATE_SHARE_ID, false);
        if (!$share) {
            return array(); // 分享不存在
        }
        $shareConfig = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHARE, GameConst::CULTIVATE_SHARE_ID, true);
        $shareIsExpire = ShareService::get()->shareIsExpire($shareConfig,$share,$reqTime);
        if ($shareIsExpire) {
            return array(); // 链接过期
        }

        $breedShareLimit = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'breedShareLimit', true);
        $breedShareTime = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'breedShareTime', true);
        $breedShareLimit = intval($breedShareLimit['value']);
        $breedShareTime = intval( $breedShareTime['value']);
        $touchUsers = $share->getRawTouchUsers();
        $cultivateTouchUsers = $share->getRawCultivateTouchUsers();
        if (count($cultivateTouchUsers) >= $breedShareLimit) {
            return array(); // 超过上限
        }

        $num1 = count($touchUsers) - count($cultivateTouchUsers);
        $num2 = $breedShareLimit - count($cultivateTouchUsers);
        $num = min($num1,$num2);
        if ($num < 1) {
            return array(); // 已加速
        }

        $landId = 21030001; // 暂时固定值  后期修改
        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId,false);
        if (!$userLand) {
            return array(); // 培育不存在
        }
        $time = $num * $breedShareTime;

        $nickname = array();
        $i = 0;
        foreach ($touchUsers as $uId) {
            if (!in_array($uId,$cultivateTouchUsers)) {
                $cultivateTouchUsers[] = $uId;
                if ($i <= $num) {
                    $nickname[] = UserService::get()->getInfo($uId, GameConst::USER_INFO_TYPE_TOWN_NAME);
                }
                $i++;
            }
        }

        $share->setCultivateTouchUsers($cultivateTouchUsers);
        $userLand->updateHarvestTime($time);

        $shareList->updateElement(GameConst::CULTIVATE_SHARE_ID, $share);
        SzPersister::get()->setVoList($shareList);
        $userLandList->updateElement($landId, $userLand);
        SzPersister::get()->setVoList($userLandList);

        return array(
            'nickname' => $nickname,
            'userLand' => $userLand->getHarvestTime(),
            'count' => count($cultivateTouchUsers)
        );
    }

    /**
     * @param $userId
     * @param $reqTime
     * @throws SzException
     */
    public function clearCultivateHarvestTime($userId,$reqTime) {
        /**
         * @var $shareList ShareVoList
         * @var $share ShareVo
         * @var NewCultivateLandVoList $userLandList
         * @var NewCultivateLandVo $userLand
         */
        $landId = 21030001; // 暂时固定值  后期修改
        $userLandList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_NEW_CULTIVATE_LAND);
        $userLand = $userLandList->getElement($landId,false);
        if (!$userLand) {
            $shareList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_SHARE);
            $share = $shareList->getElement(GameConst::CULTIVATE_SHARE_ID, false);
            if (!$share) {
                return; // 分享不存在
            }

            $shareConfig = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHARE, GameConst::CULTIVATE_SHARE_ID, true);
            $shareIsExpire = ShareService::get()->shareIsExpire($shareConfig,$share,$reqTime);
            if ($shareIsExpire) {
                return; // 链接过期
            }

            $breedShareLimit = SzConfig::get()->loadAppConfig(ModuleProfileConst::CONFIG_PROFILE, 'breedShareLimit', true);
            $touchUsers = $share->getRawTouchUsers();
            $cultivateTouchUsers = $share->getRawCultivateTouchUsers();
            if (count($cultivateTouchUsers) >= $breedShareLimit) {
                return; // 超过上限
            }
            $num = count($touchUsers) - count($cultivateTouchUsers);
            if ($num < 1) {
                return; // 已加速
            }
            $cultivateTouchUsers = $touchUsers;
            $share->setCultivateTouchUsers($cultivateTouchUsers);
            $shareList->updateElement(GameConst::CULTIVATE_SHARE_ID, $share);
            SzPersister::get()->setVoList($shareList);
        }
        return;
    }

    /**
     * @param $userId
     * @return int
     * @throws SzException
     */
    public function getCultivateTouchUsers($userId) {
        /**
         * @var $shareList ShareVoList
         * @var $share ShareVo
         */
        $reqTime = GameService::get()->getReqTime();
        $shareList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_SHARE);
        $share = $shareList->getElement(GameConst::CULTIVATE_SHARE_ID, false);
        if (!$share) {
            return 0; // 分享不存在
        }
        $shareConfig = SzConfig::get()->loadAppConfig(GameConst::CONFIG_SHARE, GameConst::CULTIVATE_SHARE_ID, true);
        $shareIsExpire = ShareService::get()->shareIsExpire($shareConfig,$share,$reqTime);
        if ($shareIsExpire) {
            return 0; // 链接过期
        }
        $cultivateTouchUsers = $share->getRawCultivateTouchUsers();
        return count($cultivateTouchUsers);
    }

}